#include "imbus_internal.h"
#include "im_server.h"

static IMBool
__im_server_listen          (IMServer       *server,
                             const IMChar   *address,
                             IMIOError      *error)
{
    return FALSE;
}

static IMBool
__im_server_is_connected    (IMServer       *server)
{
    return FALSE;
}

static void
__im_server_disconnect      (IMServer       *server)
{
}

static void
__im_server_set_main_loop   (IMServer       *server,
                             IMMainLoop     *loop)
{
}

static IMMainLoop *
__im_server_get_main_loop   (IMServer       *server)
{
    return 0;
}

static void
__im_server_set_new_connection_handler  (IMServer               *server,
                                         IMNewConnectionHandler  handler,
                                         IMPointer               data,
                                         IMDestroyFunc           data_destroy_func)
{
}


static void
__im_server_copy (IMPointer      dest,
                  IMConstPointer src)
{
    _im_assert_not_reached("IMServer objects couldn't be copied.\n");
}

static IMBool
__im_server_serialize (IMConstPointer obj,
                       IMPointer      stream)
{
    _im_assert_not_reached("IMServer objects couldn't be serialized.\n");
    return FALSE;
}

static IMBool
__im_server_deserialize (IMPointer      obj,
                         IMPointer      stream)
{
    _im_assert_not_reached("IMServer objects couldn't be deserialized.\n");
    return FALSE;
}

static void
__im_server_class_init (IMPointer klass)
{
    IMObjectClass *ocp = (IMObjectClass *)klass;
    IMServerClass *scp = (IMServerClass *)klass;

    ocp->copy               = __im_server_copy;
    ocp->serialize          = __im_server_serialize;
    ocp->deserialize        = __im_server_deserialize;

    scp->listen             = __im_server_listen;
    scp->is_connected       = __im_server_is_connected;
    scp->disconnect         = __im_server_disconnect;
    scp->set_main_loop      = __im_server_set_main_loop;
    scp->get_main_loop      = __im_server_get_main_loop;
    scp->set_new_connection_handler = __im_server_set_new_connection_handler;
}

static void
__im_server_initialize (IMPointer obj)
{
}

static void
__im_server_finalize (IMPointer obj)
{
}

void
__im_type_register_server ()
{
    static IMTypeInfo im_server_type_info = 
    {
        sizeof (IMServerClass), /**< class_size >**/
        __im_server_class_init, /**< class_init >**/
        0,                          /**< class_finalize >**/

        sizeof (IMServer),      /**< instance_size >**/
        __im_server_initialize, /**< instance_init >**/
        __im_server_finalize,   /**< instance_finalize >**/
    };

    __im_type_register_builtin_class (IM_TYPE_INITIALLY_OWNED,
                                      IM_TYPE_SERVER,
                                      "Server",
                                      &im_server_type_info,
                                      FALSE);
}

IMServer*
im_server_new (IMType type)
{
    IMServer *server;
    _im_return_val_if_fail (type != IM_TYPE_SERVER &&
                            im_type_is_a (type, IM_TYPE_SERVER), 0);
    server = (IMServer *) im_object_new (type);
    _im_assert (server);
    return server;
}

IMServer*
im_server_new_listen (const IMChar  *address,
                      IMIOError     *error)
{
    IMServer *server;
    /* TODO: Only support IMServerUnix for now. */
    server = (IMServer *) im_object_new (IM_TYPE_SERVER_UNIX);
    _im_assert (server);
    if (!IM_SERVER_GET_CLASS(server)->listen (server, address, error)) {
        im_object_unref (server);
        server = 0;
    }
    return server;
}

IMBool
im_server_listen (IMServer      *server,
                  const IMChar  *address,
                  IMIOError     *error)
{
    _im_return_val_if_fail (IM_IS_SERVER(server), FALSE);
    _im_return_val_if_fail (address && *address, FALSE);

    return IM_SERVER_GET_CLASS(server)->listen (server, address, error);
}

IMBool
im_server_is_connected (IMServer *server)
{
    _im_return_val_if_fail (IM_IS_SERVER(server), FALSE);
    return IM_SERVER_GET_CLASS(server)->is_connected (server);
}

void
im_server_disconnect (IMServer *server)
{
    _im_return_if_fail (IM_IS_SERVER(server));
    IM_SERVER_GET_CLASS(server)->disconnect (server);
}

void
im_server_set_main_loop (IMServer   *server,
                         IMMainLoop *loop)
{
    _im_return_if_fail (IM_IS_SERVER(server));
    _im_return_if_fail (IM_IS_MAIN_LOOP(loop));
    IM_SERVER_GET_CLASS(server)->set_main_loop (server, loop);
}

IMMainLoop *
im_server_get_main_loop (IMServer   *server)
{
    _im_return_val_if_fail (IM_IS_SERVER(server), 0);
    return IM_SERVER_GET_CLASS(server)->get_main_loop (server);
}

void
im_server_set_new_connection_handler (IMServer               *server,
                                      IMNewConnectionHandler  handler,
                                      IMPointer               data,
                                      IMDestroyFunc           data_destroy_func)
{
    _im_return_if_fail (IM_IS_SERVER(server));
    _im_return_if_fail (handler != 0);
    IM_SERVER_GET_CLASS(server)->set_new_connection_handler (server,
                                                             handler,
                                                             data,
                                                             data_destroy_func);
}

/*
vi:ts=4:nowrap:ai:expandtab
*/
